﻿using System;
using System.Collections.Generic;
using System.Linq;
using CcrFlows.Internal.Stages;
using Microsoft.Ccr.Core;
using NUnit.Framework;

namespace Test.CcrFlows
{
    [TestFixture]
    public class testSeqStage
    {
        [Test]
        public void Create_stage()
        {
            StageBase stage = new SeqStage<int, string>((i, ps) => ps.Post(i + "x"));

            string t;
            stage.Input.First().Post(99);
            Assert.IsTrue(((Port<string>) stage.Output.First()).WaitFor(500, out t));
            Assert.AreEqual("99x", t);

            stage.Input.First().Post(123);
            Assert.IsTrue(((Port<string>)stage.Output.First()).WaitFor(500, out t));
            Assert.AreEqual("123x", t);
        }


        [Test]
        public void Concatenate_stages()
        {
            StageBase stage1 = new SeqStage<int, string>((i, ps) =>ps.Post(i + "x"));

            string t;
            stage1.Input.First().Post(0);
            Assert.IsTrue(((Port<string>)stage1.Output.First()).WaitFor(500, out t));

            StageBase stage2 = new SeqStage<string, string>((s, ps) =>ps.Post(s + "y"));
            stage1.ContinueWith(0, stage2);

            stage1.Input.First().Post(99);
            Assert.IsTrue(((Port<string>)stage2.Output.First()).WaitFor(500, out t));
            Assert.AreEqual("99xy", t);
        }


        [Test]
        public void Create_iterator_stage()
        {
            SplitWithIterator swi = new SplitWithIterator();

            StageBase iteratorStage = new SeqStage<int, string>(swi.GenerateStringsWithIterator);
            //StageBase iteratorStage = new SeqStage<int, string>(swi.GenerateStringsWithPort);
            StageBase checkStage = new SeqStage<string, bool>(swi.ReceiveStrings);
            iteratorStage.ContinueWith(0, checkStage);

            iteratorStage.Input.First().PostUnknownType(3);

            bool b;
            Port<bool> output = (Port<bool>) checkStage.Output.First();
            Assert.IsTrue(output.WaitFor(500, out b));
            Assert.IsTrue(output.WaitFor(500, out b));
            Assert.IsTrue(output.WaitFor(500, out b));
        }
    }


    class SplitWithIterator
    {
        public void GenerateStringsWithPort(int input, Port<string> output)
        {
            Console.WriteLine("input {0}", input);

            for(int i=0; i<input; i++)
            {
                Console.WriteLine("gen {0}", i);
                output.Post(i.ToString());
            }
        }

        public IEnumerator<string> GenerateStringsWithIterator(int input)
        {
            Console.WriteLine("input {0}", input);

            for (int i = 0; i < input; i++)
            {
                Console.WriteLine("gen {0}", i);
                yield return i.ToString();
            }
        }

        public void ReceiveStrings(string s, Port<bool> output)
        {
            Console.WriteLine("recv {0}", s);
            output.Post(true);
        }
    }
}
